import json
from django.http import JsonResponse
from django.shortcuts import render
from django_redis import get_redis_connection

from apps.goods.models import SKU
# Create your views here.
from utils.user import LoginRequiredJSONMixin
from django.views import View

"""
购物车的增删改查

增
        前端:         当用户点击添加购物车的时候,会发送ajax请求 .请求携带 商品id,商品数量.请求头中携带cookie [sessionid]
                      添加购物车默认选中,所以 选中状态 提交可选
        后端:
            请求:
                        POST            /carts/         body   JSOn
            业务:
                        1. 接收参数
                        2. 提取参数
                        3. 验证参数
                        4. 数据入库(redis)
                            4.1 链接redi
                            4.2 操作hash
                            4.3 操作set
                        5. 返回响应 
            响应:
                        code:0

查
        前端:         访问购物车列表页面
        后端:
                请求:     GET     /carts/
                业务:
                        1.根据需求查询数据 (redis)
                            1.1 链接redis
                            1.2 获取hash
                            1.3 获取set
                            1.4 根据商品的id查询商品的详细信息
                        2.将对象转换为字典数据
                        3.返回响应
                响应:

改
        ① 只要修改了一个商品的数量或者是选中状态 就发送请求
        ② 发送修改的数据 有 商品id和商品数量 以及 选中状态
        ③ 传递数量 可以传递 +1或者-1  也可以传递最终的数量值 7 10

        前端:
                当用户修改选中状态 或者修改数量的时候.发送ajax 请求.  商品id和商品数量 以及 选中状态
        后端:

            请求:     PUT         /carts/         body        JSON
            逻辑:

                        1. 接收参数
                        2. 提取参数
                        3. 验证参数
                        4. 数据更新
                            4.1 链接redis
                            4.2 更新hash
                            4.3 更新set
                        5. 返回响应   
            响应:
                    code:0 ,count: 最终的数量

删   
        前端:
                用户点击删除按钮, 前端发送ajax请求. 请求携带 sku_id
        后端:
            请求:
                    DELETE      carts/      body    JSON

            逻辑:
                    1.接收数据
                    2.提取数据
                    3.根据id查询数据
                    4.删除数据
                        4.1 链接redis
                        4.2 删除hash
                        4.3 删除set
                    5.返回响应
            响应:
                    code:0
"""


class CartsView(LoginRequiredJSONMixin, View):
    """购物车管理"""

    def post(self, request):
        """添加购物车"""
        # 1. 接收参数
        data = json.loads(request.body.decode())
        # 2. 提取参数
        sku_id = data.get('sku_id')
        count = data.get('count')

        # 3. 验证参数
        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必传参数'})

        try:
            SKU.objects.get(id=sku_id)

        except SKU.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '商品不存在'})

        try:
            count = int(count)
        except Exception:
            count = 1

        # 4. 数据入库(redis)
        redis_cli = get_redis_connection('carts')
        # 不能用hset，需要用hincrby来进行累加
        # redis_cli.hset('carts_%s' % request.user.id, sku_id, count)
        redis_cli.hincrby('carts_%s' % request.user.id, sku_id, count)
        redis_cli.sadd('selected_%s' % request.user.id, sku_id)

        return JsonResponse({'code': 0, 'count': count})

    def get(self, request):
        # 1.根据需求查询数据 (redis)

        #     1.1 链接redis
        redis_cli = get_redis_connection('carts')

        #     1.2 获取hash
        redis_cart = redis_cli.hgetall('carts_%s' % request.user.id)
        #     1.3 获取set
        cart_selected = redis_cli.smembers('selected_%s' % request.user.id)
        #     1.4 根据商品的id查询商品的详细信息

        print(redis_cart)

        # 2.将对象转换为字典数据
        data_list = []
        for sku_id, count in redis_cart.items():
            sku = SKU.objects.get(id=sku_id)
            data_list.append({
                'id': sku.id,
                'count': int(count),
                'selected': sku_id in cart_selected,
                'amount': int(count) * int(sku.price),
                'name': sku.name,
                'price': int(sku.price),
                'default_image_url': sku.default_image.url
            })

        # 3.返回响应
        return JsonResponse({'code': 0,
                             'errmsg': 'ok',
                             'cart_skus': data_list
                             })

    def put(self, request):

        # 1.接收参数
        json_data = json.loads(request.body.decode())
        # 2. 提取参数
        sku_id = json_data.get('sku_id')
        count = json_data.get('count')
        selected = json_data.get('selected')
        # 3. 验证参数
        if not all([count, sku_id]):
            return JsonResponse({'code': 400, 'errmsg': '错误'})
        # 4. 数据更新
        #     4.1 链接redis
        redis_cli = get_redis_connection('carts')

        #     4.2 更新hash
        redis_cli.hset('carts_%s' % request.user.id, sku_id, count)
        #     4.3 更新set
        if selected:
            redis_cli.sadd('selected_%s' % request.user.id, sku_id)

        else:
            redis_cli.srem('selected_%s' % request.user.id, sku_id)
        # 5. 返回响应
        return JsonResponse({'code': 0, 'cart_sku': {'count': count, 'selected': selected}})

    def delete(self, request):
        # 1.接收数据
        json_data = json.loads(request.body.decode())
        # 2.提取数据
        sku_id = json_data.get('sku_id')

        # 3.根据id查询数据
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            JsonResponse({'code': 400, 'errmsg': '商品不存在'})

        # 4.删除数据
        #     4.1 链接redis
        redis_cli = get_redis_connection('carts')
        #     4.2 删除hash
        redis_cli.hdel('carts_%s' % request.user.id, sku_id)
        #     4.3 删除set
        redis_cli.srem('selected_%s' % request.user.id, sku_id)
        # 5.返回响应
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok'
        })


from utils.user import LoginRequiredJSONMixin


class SelectAllView(LoginRequiredJSONMixin, View):
    """全选购物车"""

    def put(self, request):
        """更新"""
        # 1. 接收参数
        json_data = json.loads(request.body.decode())

        # 2. 提取参数
        selected = json_data.get('selected', True)
        # 3. 更新数据
        # 3.1 链接redis
        redis_cli = get_redis_connection('carts')
        # 3.2 更新数据
        carts_ids = redis_cli.hgetall('carts_%s' % request.user.id)
        sku_id_list = carts_ids.keys()
        if selected:
            redis_cli.sadd('selected_%s' % request.user.id, *sku_id_list)
        else:
            redis_cli.srem('selected_%s' % request.user.id, *sku_id_list)
        return JsonResponse({'code': 0,
                             'errmsg': '全选购物车成功'})


class CartsSimpleView(View):
    def get(self, request):
        user = request.user

        # 链接数据库
        redis_cli = get_redis_connection('carts')
        redis_cart = redis_cli.hgetall('carts_%s' % user.id)
        cart_selected = redis_cli.smembers('select_%s' % user.id)
        cart_dict = {}
        for sku_id, count in redis_cart.items():
            cart_dict[int(sku_id)] = {
                'count': int(count),
                'selected': sku_id in cart_selected
            }

        carts_ids = redis_cart.keys()
        data_list = []
        skus = SKU.objects.filter(id__in=carts_ids)
        for sku in skus:
            data_list.append({
                'id': sku.id,
                'name': sku.name,
                'count': cart_dict.get(sku.id).get('count'),
                'default_image_url': sku.default_image.url
            })

        # 响应json列表数据
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'cart_skus': data_list})
